#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2025/3/5 19:13
# @Author  : 麦伟贤


from datetime import datetime,time as dt_time
import time
import logging
import os
from logging.handlers import TimedRotatingFileHandler
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.common import TimeoutException, NoSuchElementException, StaleElementReferenceException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


"""
资产域->5min工单签收脚本2.1
1.修改了日志
2.修改签单逻辑，每次之前第一张单，避免循环签单中出现的元素过期问题
3.如果屏幕分辨率过大，请缩小浏览器分辨率，保证查询按钮可见
"""

# 常量定义
login_time = 45
circle_time = 30
LOGIN_URL = "http://10.141.12.203:8007/up/user/userdesktop/index"
download_dir = r"download"
LOG_DIR = r"log"
SITE = '电网管理平台（资产域）'
PAGE = "配网故障抢修管理"



def customer_namer():
    """
    生成按日期命名的日志文件名
    :return:
    """
    timestamp = datetime.now().strftime("%Y-%m-%d")
    return timestamp

def setup_logging():
    """
    日志配置
    :return:
    """
    if not os.path.exists(LOG_DIR):
        try:
            os.makedirs(LOG_DIR,exist_ok=True)
            logging.info(f"'{LOG_DIR}' 已创建")
        except Exception as e:
            logging.error(f"创建日志失败目录：{e}")
            raise
    # 基础日志文件路径
    log_file = os.path.join(LOG_DIR, f"app_{customer_namer()}.log")



    # 按天轮转的Handler
    file_handler = TimedRotatingFileHandler(filename=log_file,
                                            when='midnight', # 每天午夜轮转
                                            backupCount=7, # 保留7天日志
                                            encoding='utf-8'
                                            )
    file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
    file_handler.suffix = "%Y-%m-%d"

    # 控制台Handler
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))

    # 配置根日志器
    logging.basicConfig(level=logging.INFO,
                        handlers=[file_handler, #输出到文件
                                  console_handler #输出到控制台
                        ]
    )



def ensure_directory(path):
    if not os.path.exists(path):
        os.makedirs(path)
        logging.info(f"‘{path}’ 已创建")
    else:
        logging.info(f"‘{path}’ 已存在")

def setup_driver():
    """设置Chrome浏览器"""
    chrome_option = Options()
    # 禁用 Web 安全
    chrome_option.add_argument("--disable-web-security")
    # 忽略 SSL 证书错误
    chrome_option.add_argument("--ignore-ssl-errors")
    # 忽略证书错误
    chrome_option.add_argument("--ignore-certificate-errors")
    # 允许不安全的 localhost
    chrome_option.add_argument("--allow-insecure-localhost")
    # 禁用下载保护
    chrome_option.add_argument("--safebrowsing-disable-download-protection")
    # 禁用扩展黑名单
    chrome_option.add_argument("--safebrowsing-disable-extension-blacklist")
    # 禁用沙盒模式
    chrome_option.add_argument('--no-sandbox')
    # 保持浏览器打开状态（默认代码执行完毕自动关闭）
    chrome_option.add_experimental_option('detach', True)
    # 设置白名单
    chrome_option.add_argument('--unsafely-treat-insecure-origin-as-secure=http://10.150.121.20:8080')
    # 设置下载目录
    ensure_directory(download_dir)
    prefs = {
        "download.default_directory": download_dir,  # 设置默认下载路径
        "download.directory_upgrade": True,  # 自动升级下载目录
        "download.prompt_for_download": False,  # 禁用下载提示
        "safebrowsing.enabled": False,  # 禁用安全浏览
    }
    chrome_option.add_experimental_option("prefs", prefs)

    driver = webdriver.Chrome(options=chrome_option)
    #driver.implicitly_wait(20)  # 设置最长等待时间20s
    return driver


def handle_popup(driver, xpath, timeout = 2):
    try:
        element = WebDriverWait(driver,timeout).until(EC.element_to_be_clickable((By.XPATH, xpath)))
        element.click()
        return True
    except:
        return False


def login_market_sys(driver):
    # 登录目标页面，电网管理平台（资产域）
    try:
        driver.get(LOGIN_URL)
        driver.maximize_window()
        wait = WebDriverWait(driver, 120)
        # login_element = wait.until(EC.element_to_be_clickable((By.ID, "btnLogin")))
        # login_element.click()
        logging.info(f"休眠{login_time}s，请尽快手动登录...")
        time.sleep(login_time)
        logging.info("休眠结束")
        logging.info("登陆成功")
        # 点击电网管理平台资产域
        search_input =  wait.until(EC.element_to_be_clickable((By.XPATH,'//input[@id="searchInput"]')))
        search_input.send_keys(SITE)
        time.sleep(1.5)
        btn_a = wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@id="header"]/div/div[1]/div/div[2]/div[2]/a')))
        btn_a.click()

        # 切换到新窗口
        new_window_handle = driver.window_handles[-1]
        driver.switch_to.window(new_window_handle)
        logging.info(f"切换到新窗口(首页)：{new_window_handle}")
        time.sleep(3)
        header_span = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="headerEl"]/div/div[1]/span')))
        header_span.click()

        #处理公告弹窗
        handle_popup(driver, '//*[@id="c5-popup0"]/div[2]/a')

        time.sleep(1)
        search_input = wait.until(EC.presence_of_element_located((By.XPATH,'//*[@id="searchApp"]')))
        search_input.send_keys(PAGE)
        search_input.send_keys(Keys.ENTER)
        time.sleep(1)
        span_btn = wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@id="gmp-hamburg-catalogue"]/div/ul/li/a/span')))
        span_btn.click()


        malfunction = driver.window_handles[-1]
        driver.switch_to.window(malfunction)
        logging.info("成功进入配网抢修页面")
        time.sleep(3.5)
        btn_order = wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@id="830F4122A1C7431D8BE2715610FE4EB2"]')))
        btn_order.click()
        logging.info("已进入工单处理页面")
        return driver.window_handles[-1]
    except (TimeoutException, NoSuchElementException) as e:
        logging.error(f"登录失败：{e}")
        return None



#监控逻辑
def monitor(driver):
    wait = WebDriverWait(driver, 60)
    # 登录目标页面
    repair_page = login_market_sys(driver)
    # 需要切换iframe
    main_iframe = driver.find_element(By.XPATH,'//*[@id="mainFrame"]')
    logging.info(main_iframe)
    driver.switch_to.frame(main_iframe)

    logging.info("有10s时间切换页面进行测试")
    time.sleep(10)
    # 现在要进入已完成页面进行测试

    try:
        while True:
            # 1.点击查询按钮，
            btn_search = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="uiid-7845711340501066"]')))
            btn_search.click()
            logging.info("查询按钮点击")
            time.sleep(5)
            # 2.获取表格，如果为空，continue
            table = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="uiid-19085839246656157"]')))
            if not table:
                logging.info("获取table失败")

            trs = table.find_elements(By.XPATH, './/tr[@id="null"]')
            if not trs:
                logging.info("获取trs失败")
            logging.info(f"当前工单数量为：{len(trs)}")
            if len(trs) == 0:
                logging.info("暂无工单")
                logging.info(f"等待{circle_time}s")
                time.sleep(circle_time)
                continue
            #3.表格不为空，处理第一张单
            first_tr = trs[0]
            if first_tr is not None:
                a = first_tr.find_element(By.TAG_NAME, 'a')
                num = a.get_attribute('textContent')
                logging.info(f"工单号{num}")
                a.click()
                time.sleep(5)

                # 切换窗口并操作
                driver.switch_to.window(driver.window_handles[-1])
                # 进入页面
                btn = driver.find_element(By.XPATH,'//button[@id="uiid-5173065957737148"]')
                # 点击按钮
                if btn:
                    #btn.click()
                    logging.info(f"已找到按钮[{btn.get_attribute('textContent')}]并点击")
                    logging.info(f"工单：{num}已签收！")
                else:
                    logging.info(f"工单：{num}找不到点击按钮")
                # 删除当前窗口，并切换句柄
                driver.close()
                driver.switch_to.window(repair_page)
                time.sleep(1)
                # 刷新页面
                driver.refresh()
                btn_order = wait.until(
                    EC.element_to_be_clickable((By.XPATH, '//*[@id="830F4122A1C7431D8BE2715610FE4EB2"]')))
                btn_order.click()
                logging.info("已进入工单处理页面")
                driver.switch_to.frame(main_iframe)
                time.sleep(8)
    except (NoSuchElementException, TimeoutException) as e:
            logging.error(f"元素加载异常: {str(e)}")
    # 触发页面刷新或重试机制
    except StaleElementReferenceException:
            logging.error("DOM结构已更新，需重新定位元素")
    except Exception as  e:
        logging.error(f"循环出错：{str(e)}")




def main():
    setup_logging()
    # 设置浏览器
    driver = setup_driver()
    monitor(driver)



if __name__ == '__main__':
    main()
